home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 9601 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  3.2 KB

  1. Path: news.delphi.com!jodle
  2. From: jodle@bix.com (jodle)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: polymorphism and style
  5. Date: 3 Mar 1996 02:10:51 GMT
  6. Organization: BIX
  7. Message-ID: <4hav3b$m26@news2.delphi.com>
  8. References: <4gr4ur$n13@alpha.pcix.com> <DnI6II.KMt@news.arco.com> <4h4h3h$6ur@brtph500.bnr.ca> <4has16$cge@werple.net.au>
  9. NNTP-Posting-Host: bix.com
  10. X-Newsreader: TIN [version 1.2 PL2]
  11.  
  12. David White (davidw@werple.net.au) wrote:
  13.  
  14. : There are many occasions when this is not practical. Suppose I have an
  15. : array of base class object pointers; at some stage I might want to iterate
  16. : over them, retrieve the derived classes, and call functions specific to the
  17. : derived type. Or I might pass an object pointer to something and receive
  18. : it back later and have to retrieve the derived class. These are exactly
  19. : the kinds of situations that 'dynamic_cast' was intended for. Your
  20. : suggestion can unnecessarily complicate the design, rather than simplify
  21. : it. To state, without qualification, that "this is clearly a design fault"
  22. : demonstrates ignorance of real situations in OO design. And this from an
  23. : OO helpline! 
  24.  
  25. I agree that the form of the message was inappropriate; an absolute
  26. condemnation of the design is not in order.  However, my experience is
  27. that this kind of situation generally arises from a design that did not
  28. have the benefit of a thorough dynamic analysis.  In general, the dynamic
  29. type of an object tends to degrade over time or function call depth.  By
  30. degrade, I mean that it tends to get upcast.  A good example is a
  31. container (barn) that holds animals ({chickens,pigs,horses}).  We discard
  32. some type information as soon as we put the animals in the barn.  Chickens
  33. are still chickens, but we can no longer differentiate between them and
  34. cows.
  35.  
  36. Often, we put the animals in the barn a little sooner than is absolutely
  37. necessary.  Often we can avoid downcasting and bloating the interface of
  38. individual objects by employing one of several techiques.  The first is to
  39. maintain multiple references to each object or subdividing the barn.  To
  40. borrow from the barn analogy further, barns often have pens in them to
  41. keep kinds of animals together.
  42.  
  43. The second is to delay upcasting.  This is not always possible, but it's
  44. always worth investigating.
  45.  
  46. The third is to use a general interface to specific operations.  If all
  47. the animals are in the barn together, there is probably some
  48. semantic reason why.  We may have put them in the barn for the night
  49. intending to let them sleep.  Pigs sleep laying down, horses sleep
  50. standing up and chickens roost.  I've seen a lot of code out there that
  51. essentially downcasts to achieve calls like pig->lay() and
  52. chicken->roost() before calling animal->sleep() for the stock.  Obviously,
  53. roost and lay are operations chickens and pigs can decide to do for
  54. themselves when it's time to sleep.  In fact, they actually decide when
  55. it's time to sleep on their own.
  56.  
  57. It's rare that I've seen a downcast that couldn't be -reasonably- avoided
  58. with one of these techniques.  I tend to work at avoiding type entropy
  59. early, during my first pass at the dynamic model when 2nd-order operations
  60. are emerging.  Taking the time to model event classes seems to help here,
  61. sometimes.
  62.